package pl.drypisy;

import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

/**
 * @author Marcin Pilat
 * @version 1.0
 */
public class PlayMapActivity extends MapActivity {
	private MapView mapView;
	private GeoPoint p;
	private MapController mc;
	private LocationManager lm;
	private MyLocationListener locationListener;
	private String provider;
	private Game game;
	private TextView pointsText;
	private TextView distanceText;
	private TextView accuracyText;
	private List<Overlay> lofO;
	private CheckpointItemizedOverlay actualOverlay;
	private int chid;
	private int rid;
	private Drawable menusat;
	private Drawable menusat2;
	private Drawable accu;
	private Drawable actMarker_black;
	private OverlayItem actItem;
	private Location actualLocation;
	private final String PREF_NAME = "Prefs";
	private final String PREF_CHP = "chid";
	private final String PREF_ROUTE = "rid";
	private final String PREF_POINTS = "points";
	private final String PREF_ACU = "accuracy";
	
	private int points = 0;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        makeGUI();
        
        //When Activity is invoked by browser Activity
        Bundle extras = getIntent().getExtras();
        //or is resumed
        SharedPreferences pref = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
        
        if (extras != null){
        	rid = extras.getInt("rid");
        	chid = 0;
        } else {
        	rid = pref.getInt(PREF_ROUTE, -1);
        	chid = pref.getInt(PREF_CHP, -1);
        	points = pref.getInt(PREF_POINTS, 0);
        }
        
        //Creating Map & layout handler
        mapView = (MapView)findViewById(R.id.mapView);
        mapView.setSatellite(false);
        mc = mapView.getController();
        //For tests//
        Button nextb = (Button)findViewById(R.id.buttonNext);
        Button taskb = (Button)findViewById(R.id.buttonTask);
        //--------//
        lofO = mapView.getOverlays();
        menusat = getResources().getDrawable(R.drawable.icon_sat_img_1);
        menusat2 = getResources().getDrawable(R.drawable.icon_sat_img_2);
        accu = getResources().getDrawable(R.drawable.icon_accuracy);
        actMarker_black = getResources().getDrawable(R.drawable.user_black_white);
        pointsText.setText(getString(R.string.points)+points);
        
        //Creating Game object
        game = new Game("Gra1", mapView, this);
        if (chid != 0){
        	game.goToCheckpoint(rid,chid,points);
        }else {
            game.start(rid);
        }
        
        //Define actual position marker overlay
		actualOverlay = new CheckpointItemizedOverlay(actMarker_black,mapView);
		
        //Adding click listener to button. Will be removed
		nextb.setOnClickListener(lisn);
		taskb.setOnClickListener(list);
        taskb.setVisibility(View.VISIBLE);
		nextb.setVisibility(View.VISIBLE);
		
        //Creating location manager and location listener
        lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        locationListener = new MyLocationListener();
        
    	setProvider();
    }
    
    private void makeGUI(){
    	setContentView(R.layout.map);
    	pointsText = (TextView)findViewById(R.id.result);
        distanceText = (TextView)findViewById(R.id.distance);
        accuracyText = (TextView)findViewById(R.id.accuracy);
    }
    
    //Choosing between GPS and network provider
    private void setProvider(){
    	
    	if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)){
    		provider = LocationManager.GPS_PROVIDER;
        	lm.requestLocationUpdates(provider, 200, 10, locationListener);
    	}else{
    		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    	    builder.setMessage(getString(R.string.unactive_gps))
    	           .setCancelable(false)
    	           .setPositiveButton(getString(R.string.btn_positive), new DialogInterface.OnClickListener() {
    	               public void onClick(DialogInterface dialog, int id) {
    	                   startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
    	                   provider = LocationManager.GPS_PROVIDER;
    	                   lm.requestLocationUpdates(provider, 200, 10, locationListener);
    	               }
    	           })
    	           .setNegativeButton(getString(R.string.btn_negative), new DialogInterface.OnClickListener() {
    	               public void onClick(DialogInterface dialog, int id) {
    	                   provider = LocationManager.NETWORK_PROVIDER;
    	                   lm.requestLocationUpdates(provider, 200, 10, locationListener);
    	            	   dialog.cancel();
    	               }
    	           });
    	    final AlertDialog alert = builder.create();
    	    alert.show();
    	}
    }
    
    //Location Listener
    private class MyLocationListener implements LocationListener
    {
    	LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    	//Overriding function which check location and starting Task intent
		public void onLocationChanged(Location location) {
			if (location != null){
				//Set actual position marker
				p = new GeoPoint((int)(location.getLatitude()*1E6) ,(int)(location.getLongitude()*1E6) );
				actItem = new OverlayItem(p, getString(R.string.overlay_here), "");
				actualOverlay.clearOverlay();
				actualOverlay.addOverlay(actItem);
				if (!(lofO.contains(actualOverlay))){
		        	lofO.add(actualOverlay);
		        }
				mapView.invalidate();
				int dist = game.checkLocation(location);
				actualLocation = location;
				setDistanceText(dist);
				setAccuracyText();
			}
		}
		
		public void onProviderDisabled(String provider) {
			if (provider.equalsIgnoreCase("GPS_PROVIDER")){
				lm.requestLocationUpdates("NETWORK_PROVIDER", 200, 10, this);
			} 
		}

		public void onProviderEnabled(String provider) {
			if (provider.equalsIgnoreCase("GPS_PROVIDER")){
				lm.requestLocationUpdates("GPS_PROVIDER", 200, 10, this);
			}
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
		}
    	
    }
    
    
    //Listener for next button. Will be removed
    OnClickListener lisn = new OnClickListener()
    {
		public void onClick(View v) {
			chid = game.next(0);
			Log.d("CHP",chid+"");
			float dist = game.checkLocation(lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
			distanceText.setText(getString(R.string.distance) + dist);
		}
	};
	
    //Listener for task button. Will be removed
    OnClickListener list = new OnClickListener()
    {
		public void onClick(View v) {
			game.goToTask();
		}
	};
	
	/** 
	 * Activity function for creating menu 
	 * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu){
		super.onCreateOptionsMenu(menu);
		menu.add(0, 0, 0, "").setIcon(menusat);
		menu.add(0, 1, 1, "").setIcon(accu);
		return true;		
	}

	/** 
	 * Activity function ehen select menu item
	 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		switch (item.getItemId()){
		case 0:
			if (mapView.isSatellite()){
				mapView.setSatellite(false);
				item.setIcon(menusat);
			} else {
				mapView.setSatellite(true);
				item.setIcon(menusat2);
			}
			return true;
		case 1:
			game.setAccuracy();
			return true;
		default:
			return false;
		}
	}
	
	
	/**
	 * Set GUI elements: distance
	 * @param dist Distance from next point to actual position
	 */
	public void setDistanceText(int dist){
		String tmpDist;
		if (dist > 1000){
			int tmp = dist%1000;
			dist /= 1000;
			tmpDist = dist + "." + tmp + " km";
		} else {
			tmpDist = dist + " m";
		}
		distanceText.setText(getString(R.string.distance) + tmpDist);
	}
	
	/**
	 * Set GUI elements: accuracy
	 */
	public void setAccuracyText(){
		SharedPreferences pref = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
        int tmpAccu = game.getAccuracy();
        if (tmpAccu == 30)
        	tmpAccu = pref.getInt(PREF_ACU, 30);
		accuracyText.setText(getString(R.string.accuracy) + tmpAccu + " + " + (int)actualLocation.getAccuracy() + " m");
	}
	
	/** 
	 * When invoked activity return result
	 * @see android.app.Activity#onActivityResult(int, int, android.content.Intent)
	 */
	@Override
	public void onActivityResult(int reqc, int resc, Intent data){
		if (reqc == 1){
			if (resc == RESULT_OK){
				String tmp = data.getDataString();
				int p = Integer.parseInt(tmp);
				points += p;
				pointsText.setText(getString(R.string.points)+points);
				chid = game.next(p);
				Log.d("CHP",chid+"");
				Location location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
				int dist = game.checkLocation(location);
				setDistanceText(dist);
				setAccuracyText();
			}
		}
	}
	
	/**
	 * Activity function. Saves actual checkpoint, route and points
	 * @see android.app.Activity#onStop()
	 */
	@Override
	public void onStop(){
		super.onStop();
		SharedPreferences pref = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
		SharedPreferences.Editor editor = pref.edit();
		
		//putting values to sharedPreferences
		editor.putInt(PREF_CHP, chid);
		editor.putInt(PREF_ROUTE, rid);
		editor.putInt(PREF_POINTS, points);
		editor.commit();
		Log.d("onStop","Wychodze! rid: " + rid + " chid: " + chid + "ponts: " + points );
	}

	/** Zoom in zoom out key event. For fun:)
	 * @see android.app.Activity#dispatchKeyEvent(android.view.KeyEvent)
	 */
	@Override
	public boolean dispatchKeyEvent(KeyEvent event){
    	int action = event.getAction();
    	int keyCode = event.getKeyCode();
    	switch(keyCode){
    	case KeyEvent.KEYCODE_VOLUME_DOWN:
    		if (action == KeyEvent.ACTION_DOWN) {
    			mc.zoomOut();
            }
            return true;
    	case KeyEvent.KEYCODE_VOLUME_UP:
    		if (action == KeyEvent.ACTION_DOWN) {
    			mc.zoomIn();
            }
            return true;
    	}
    	return super.dispatchKeyEvent(event);
    }

	/* Google statistic function. Must be implemented
	 * @see com.google.android.maps.MapActivity#isRouteDisplayed()
	 */
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
}